package sg.edu.nus.iss.vmcs.customer;

import java.util.ArrayList;

import sg.edu.nus.iss.vmcs.machinery.MachineryController;
import sg.edu.nus.iss.vmcs.store.CashStore;
import sg.edu.nus.iss.vmcs.store.CashStoreController;
import sg.edu.nus.iss.vmcs.store.CashStoreItem;
import sg.edu.nus.iss.vmcs.store.CashStoreIterator;
import sg.edu.nus.iss.vmcs.store.Coin;
import sg.edu.nus.iss.vmcs.store.DrinkStoreController;
import sg.edu.nus.iss.vmcs.store.DrinksStoreItem;
import sg.edu.nus.iss.vmcs.store.StoreItem;
import sg.edu.nus.iss.vmcs.util.VMCSException;

public class Facade {
	private static Facade instance;
	private CustomerPanel customerPanel;
	private CashStoreController cashStoreController;
	private DrinkStoreController drinkStoreController;
	private MachineryController machineryController;

	private Facade() {
		
	}
	
	public static Facade getInstance() {
		if (instance == null) {
			instance = new Facade();
		}
		return instance;
	}
	
	public void setCustomerPanel(CustomerPanel cp) {
		customerPanel = cp;
	}
	
	public void setCashStoreController(CashStoreController csc) {
		cashStoreController = csc;
	}
	
	public void setDrinkStoreController(DrinkStoreController dsc) {
		drinkStoreController = dsc;
	}
	
	public void setMachineryController(MachineryController mc) {
		machineryController = mc;
	}

	public void resetChange() {
		customerPanel.resetChange();
	}

	public void startCoinReceiver() {
		customerPanel.setCoinInputBoxActive(true);
		customerPanel.setTotalMoneyInserted(0);
	}

	public void setCoinInputBoxActive(boolean active) {
		customerPanel.setCoinInputBoxActive(active);
	}

	public Coin receiveCoin(double weight, int totalInserted) {
		CashStore cashStore = (CashStore) cashStoreController.getStore();
		Coin coin = cashStore.findCoin(weight);
		if (coin == null) {
			customerPanel.displayInvalidCoin(true);
			customerPanel.setChange("Invalid Coin");
		} else {
			customerPanel.setCoinInputBoxActive(false);
			customerPanel.displayInvalidCoin(false);
			customerPanel.setTotalMoneyInserted(totalInserted + coin.getValue());
			customerPanel.setChange("");
		}
		return coin;
	}

	public void storeCash(ArrayList<Coin> arlCoins) throws VMCSException {
		for (int i = 0; i < arlCoins.size(); i++) {
			Coin coin = (Coin) arlCoins.get(i);
			machineryController.storeCoin(coin);
		}
		customerPanel.setTotalMoneyInserted(0);
	}

	public void refundCash(int totalInserted) {
		customerPanel.setChange(totalInserted);
		customerPanel.setTotalMoneyInserted(0);
		customerPanel.displayInvalidCoin(false);
	}

	public void giveChange(int changeRequired) throws VMCSException {
		int changeBal = changeRequired;
		CashStoreIterator iter = (CashStoreIterator) cashStoreController.getStore().createStoreIterator();
		iter.prepareReverse();
		while (iter.hasPrev()) {
			StoreItem cashStoreItem = iter.prev();
			int quantity = cashStoreItem.getQuantity();
			Coin coin = (Coin) cashStoreItem.getContent();
			int value = coin.getValue();
			int quantityRequired = 0;
			while (changeBal > 0 && changeBal >= value && quantity > 0) {
				changeBal -= value;
				quantityRequired++;
				quantity--;
			}
			machineryController.giveChange(iter.currentIndex(), quantityRequired);
		}
		customerPanel.setChange(changeRequired - changeBal);
		if (changeBal > 0)
			customerPanel.displayChangeStatus(true);
	}

	public void displayChangeStatus() {
		if (customerPanel == null)
			return;
		boolean isAnyDenoEmpty = false;
		StoreItem[] cashStoreItems = cashStoreController.getStore().getItems();
		for (int i = 0; i < cashStoreItems.length; i++) {
			StoreItem storeItem = cashStoreItems[i];
			CashStoreItem cashStoreItem = (CashStoreItem) storeItem;
			int quantity = cashStoreItem.getQuantity();
			if (quantity == 0)
				isAnyDenoEmpty = true;
		}
		customerPanel.displayChangeStatus(isAnyDenoEmpty);
	}

	public void updateDrinkPanel() {
		if (customerPanel == null) {
			return;
		}
		int storeSize = drinkStoreController.getStoreSize();
		for (int i = 0; i < storeSize; i++) {
			DrinksStoreItem storeItem = (DrinksStoreItem) drinkStoreController.getStoreItem(i);
			int quantity = storeItem.getQuantity();
			String name = storeItem.getName();
			int price = storeItem.getPrice();
			customerPanel.getDrinkSelectionBox().update(i, quantity, price, name);
		}
	}

	public void allowSelection(boolean allow) {
		if (customerPanel == null) {
			return;
		}
		DrinkSelectionBox drinkSelectionBox = customerPanel.getDrinkSelectionBox();
		int storeSize = drinkStoreController.getStoreSize();
		for (int i = 0; i < storeSize; i++) {
			drinkSelectionBox.setState(i, allow);
			StoreItem storeItem = drinkStoreController.getStoreItem(i);
			int quantity = storeItem.getQuantity();
			if (quantity == 0)
				drinkSelectionBox.setItemState(i, true);
		}
	}

	public void dispenseDrink(int selectedBrand) throws VMCSException {
		machineryController.dispenseDrink(selectedBrand);
		DrinksStoreItem drinkStoreItem = (DrinksStoreItem) drinkStoreController.getStore().getStoreItem(selectedBrand);
		String drinksName = drinkStoreItem.getName();
		int price = drinkStoreItem.getPrice();
		int quantity = drinkStoreItem.getQuantity();
		customerPanel.setCan(drinksName);
		customerPanel.getDrinkSelectionBox().update(selectedBrand, quantity, price, drinksName);
	}
}
